#pragma once

class CClassInfo;
class CFunctionInfo;
class CFieldInfo;
class CEnumInfo;

#include <map>
#include <vector>
#include <string>
#include <memory>
#include <optional>
#include <variant>


using MetaValue= std::optional<std::variant<std::u8string, std::vector<std::u8string>,double>>;
using MetaMap=std::map<std::u8string, MetaValue>;

class CToken;

class CFieldInfo
{
public:
    MetaMap Meta;
    std::u8string Name;
    std::u8string Type;
    bool IsReadOnly=false;
    //bool IsVirtual=false;

    std::shared_ptr<CToken> ErrorToken;
};

class CPropertyInfo
{
public:
    MetaMap Meta;
    std::u8string Name;
    std::u8string Type;

    bool IsReadOnly=false;
    std::u8string GetterFunctionName;
    std::optional<std::u8string> SetterFunctionName;

    std::shared_ptr<CToken> ErrorToken;
};

enum class EClassType
{
    Class,
    Struct,
    Interface
};

class CClassInfo
{
public:
    MetaMap Meta;
    std::u8string Name;
    std::u8string BaseClassName;
    std::shared_ptr<CClassInfo> BaseClass;
    std::vector<std::u8string> ImplementedInterfaces;
    std::vector<std::shared_ptr<CFieldInfo>> Fields;
    std::vector<std::shared_ptr<CPropertyInfo>> Properties;
    std::vector<std::shared_ptr<CFunctionInfo>> Functions;
    std::vector<std::shared_ptr<CFunctionInfo>> VirtualFunctionTable;


    EClassType ClassType=EClassType::Class;
    bool IsClass() const { return ClassType==EClassType::Class; }
    bool IsStruct() const { return ClassType==EClassType::Struct; }
    bool IsInterface() const { return ClassType==EClassType::Interface; }

    std::optional<std::u8string> ExportMacro;
    bool bIsVirtualFunctionTableGenerated=false;
    void GenerateVirtualFunctionTable();

    //start from 0
    //RCLASS/RSTRUCT/RINTERFACE line number
    int32_t RCLASSLineNumber=-1;

    //ROBJECT line number
    int32_t ROBJECTLineNumber=-1;


};

class CFunctionInfo
{
public:
    MetaMap Meta;
    std::u8string Name;
    std::u8string ReturnType;
    bool IsStatic=false;
    bool IsVirtual=false;
    bool IsConst=false;
    std::vector<std::u8string> ParameterTypes; //type name
    std::vector<std::u8string> DecoratedParameterTypes; //type name with const/*/&
};

class CEnumInfo
{
public:
    MetaMap Meta;
    std::u8string Name;
    std::vector<std::u8string> Values;
};
